extends CharacterBody2D

enum {MOVE, ATTACK, USE_PROP, INTERACTIVE}		# 模式

# 物理模拟
@export var speed = 100				## 最大速度
@export var friction = 1000			## 摩擦力, 建议值 速度:摩擦力 = 1:10
@export var acceleration = 1000		## 加速度, 建议值 速度:加速度 = 1:10

# 预加载
@onready var sprite = $Sprite2D					## 贴图
@onready var animationPlayer = $AnimationPlayer ## 动画播放对象
@onready var playerBox = $".."					## 父容器
@onready var nowWeapons = $NowWeapon			## 当前武器节点
@onready var stateObj = $State					## 状态节点
@onready var boomUI = $"../CanvasLayer/BoomUI"	## 炸弹数量UI
@onready var keyUI = $"../CanvasLayer/KeyUI"	## 钥匙数量UI
@onready var hpUI = $"../CanvasLayer/HP_UI"		## 血量UI
@onready var bag = $"../CanvasLayer/Bag"		## 背包
@onready var money = $"../CanvasLayer/MoneyUI"	## 金钱
@onready var minMap = $"../../CanvasLayer/MinMap"	## 小地图
@onready var api = Api.new()					## 网络请求工具类

# 预加载
# 工具代码
@onready var util = Util.new()
# 爆炸动画
@onready var boom = load("res://Props/tscn/boom/Boom.tscn")
# 死亡动画
@onready var deathEffect = load("res://Effect/tscn/DeathEffect.tscn")
# 受伤动画
@onready var hurtEffect = load("res://Effect/tscn/HurtEffect.tscn")

# 其他变量
var state = MOVE			## 当前状态
var isFire = false			## 是否开火
var direction = null		## 方向, 给其他类用的
var nodeName = 0
var isInteractive = false 	## 玩家是否做出交互动作

func _ready():
	stateObj.connect("death", death)
	stateObj.connect("hurt", hurt)
	stateObj.connect("addArmor", armor)
	stateObj.connect("cure", cure)


func cure(x):
	hpUI.addX(x)

'''
	这个每帧自动调用一次
	@param delta 每帧之间的时间间隔
'''
func _physics_process(delta):
	match state:
		MOVE:
			move(delta)
		ATTACK:
			attack(delta)
		USE_PROP:
			useProp(delta)
		INTERACTIVE:
			interactive(delta)
	

## 叠甲事件
func armor(x):
	# 修改UI
	hpUI.addArmorX(x)
	
'''
	死亡事件
'''
func death():
	# 发起网络请求, 统计死亡次数
	var root = get_tree().root.get_child(0)
	api.updateOrCreate(
		root,
		root.mac,
		{"deathCount": 1},
		func (_data):
			pass
	)
	
	# 加载死亡动画
	var effect = deathEffect.instantiate()
	effect.global_position = global_position
	get_tree().root.add_child(effect)
	
	# 清除自身
	queue_free()


## 当玩家拾取道具就会被调用
## @param prop 道具本体
func collection(prop):
	# 将道具放到背包, 并返回是否添加成功
	return bag.add(prop)
	
'''
	受伤事件
'''
func hurt(x):
	# 加载受伤动画
	var effect = hurtEffect.instantiate()
	effect.global_position = global_position
	get_tree().root.add_child(effect)
	# 修改UI
	hpUI.subX(x)


func interactive(_delta):
	# 改变完交互状态后马上切换回移动模式
	isInteractive = true
	state = MOVE
	
	
'''
	释放道具
'''
func useProp(_delta):
	state = MOVE
	# 只有炸弹大于1才能释放
	if boomUI.getNum() > 0:
		var boomObj = boom.instantiate()
		boomObj.position = position
		get_tree().root.get_child(0).add_child(boomObj)
		boomUI.sub()
	

func attack(_delta):
	state = MOVE
	# 使所有武器开火
	for weapon in nowWeapons.get_children():
		weapon.fire()
	
	
func success(mapConfig):
	minMap.mapConfig = mapConfig
	minMap.init_minimap()
	minMap.update_minimap(Vector2.ZERO)

		
'''
	移动函数
	@param delta 每帧之间的时间间隔
'''
func move(delta):
	# 使用道具模式
	if Input.is_action_just_pressed("useProp"):
		state = USE_PROP
		# TEST
		var generate = GenerateMap.new()
		
		minMap.mapConfig = generate.generate_map_exsit_boss()
		minMap.init_minimap()
		minMap.update_minimap(Vector2.ZERO)
		
	# 攻击模式
	if Input.is_action_just_pressed("attack"):
		state = ATTACK
		
	# 交互模式
	if Input.is_action_just_pressed("interactive"):
		state = INTERACTIVE
		
	if Input.is_action_just_pressed("1"):
		bag.consume(0)
	elif Input.is_action_just_pressed("2"):
		bag.consume(1)
	elif Input.is_action_just_pressed("3"):
		bag.consume(2)
	elif Input.is_action_just_pressed("4"):
		bag.consume(3)
	elif Input.is_action_just_pressed("5"):
		bag.consume(4)
		
	'''
		Vector2(x, y)
		x = Input.get_axis("ui_left", "ui_right")	点left返回-1, 否则1
		y = Input.get_axis("ui_up", "ui_down")		点up返回-1, 否则1
	'''
	var vector2 = Vector2(Input.get_axis("ui_left", "ui_right"), Input.get_axis("ui_up", "ui_down"))
	# 用了勾股定理, 计算使对象斜向移动的距离
	vector2 = vector2.normalized()
	
	# 当向量不等于0时, 也就是角色在运动
	if vector2 != Vector2.ZERO:
		'''
			保存玩家的方向, 可以确认玩家点击的按键
			玩家推箱子时会使用到这个变量
			玩家开枪会用到
			
			以及后坐力也会用到
		'''
		direction = vector2
		# 设置动画的朝向
		sprite.flip_h = direction.x < 0
		# 播放跑步动画
		animationPlayer.play("RightRun")
		'''
			加速度模拟
			以delta * acceleration的速度移动, 缓慢接近vector2 * speed速度
			- delta 每帧之间的时间间隔, 防止不同帧率位移距离不一样
			- velocity.x 	水平方向, -1左, 1右
			- acceleration 	加速度
			
			vector2 * speed 展开:
				Vector2(vector2.x * speed, vector2.y * speed)
		'''
		velocity = velocity.move_toward(direction * speed, delta * acceleration)
	else:
		'''
			摩擦力模拟
			否则向量为0, 代表角色停止运动了
			那么向量以delta * friction的速度靠近0向量
			- FRICTIO 摩擦力, 以这个摩擦系数缓慢靠近0速度
		'''
		velocity = velocity.move_toward(Vector2.ZERO, delta * friction)
		# 最后播放停止动画
		animationPlayer.play("RightStop")
	
	# 模拟碰撞的行走
	# 对象碰撞到刚体会被定在原地
	move_and_collide(velocity * delta)
	
	'''
		模拟滑动的行走
		对象碰到刚体, 会从上面滑落
		不用这个的原因是, 玩家推箱子会跟着箱子滑动
	'''
	# move_and_slide()
